package com.baoyouqun.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baoyouqun.base.SystemConstant;
import com.baoyouqun.base.utils.ConvertUtils;
import com.baoyouqun.base.utils.ExcelTool;
import com.baoyouqun.domain.CreateCmd.DemandCreateCmd;
import com.baoyouqun.domain.Enum.DemandCollectionTypeEnum;
import com.baoyouqun.domain.Enum.DemandInteractTypeEnum;
import com.baoyouqun.domain.Enum.DemandSortEnum;
import com.baoyouqun.domain.Enum.IndustryEnum;
import com.baoyouqun.domain.Query.AdminDemandQuery;
import com.baoyouqun.domain.Query.DemandQuery;
import com.baoyouqun.domain.Query.DemandUserQuery;
import com.baoyouqun.domain.UpdateCmd.DemandUpdateCmd;
import com.baoyouqun.domain.VO.DemandVO;
import com.baoyouqun.domain.VO.UserSimpleVO;
import com.baoyouqun.entity.Demand;
import com.baoyouqun.entity.DemandInteract;
import com.baoyouqun.entity.User;
import com.baoyouqun.mapper.DemandMapper;
import com.baoyouqun.service.*;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.StringUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.OutputStream;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DemandServiceImpl extends ServiceImpl<DemandMapper, Demand> implements DemandService {


    @Resource
    DemandCollectionService demandCollectionService;
    @Resource
    private DemandMapper demandMapper;
    @Resource
    private UserService userService;
    @Resource
    private UserResourceService userResourceService;
    @Resource
    private SystemConfigService systemConfigService;
    @Resource
    @Lazy
    private DemandInteractServiceImpl demandInteractServiceImpl;
    @Resource
    private UserVipTimeServiceImpl userVipTimeServiceImpl;
    @Resource
    private CityService cityService;
    @Resource
    private UserFollowPostTypeService userFollowPostTypeService;

    @Override
    public SingleResponse<DemandVO> create(DemandCreateCmd cmd) {
        Demand entity =
                ConvertUtils.copyBean(cmd, Demand.class);
        Boolean result = save(entity);
        if (!result) {
            return SingleResponse.buildFailure("100101", "创建失败");
        }

        DemandVO vo =
                ConvertUtils.copyBean(entity, DemandVO.class);
        return SingleResponse.of(vo);
    }


    @Override
    public Response update(DemandUpdateCmd cmd) {
        if (Objects.isNull(cmd)) {
            return Response.buildFailure("100301", "参数不能为空");
        }
        if (StringUtil.isBlank(cmd.getId())) {
            return Response.buildFailure("100302", "ID不能为空");
        }
        Demand oldEntity = getById(cmd.getId());
        if (Objects.isNull(oldEntity)) {
            return Response.buildFailure("100303", "未查询到此数据");
        }
        oldEntity = ConvertUtils.copyBean(cmd, Demand.class);
        boolean result = updateById(oldEntity);
        if (result) {
            return Response.buildSuccess();
        } else {
            return Response.buildFailure("100304", "更新失败");
        }
    }

    /**
     * 访问数加1（数据库层面原子操作，避免并发问题）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Demand incrementViewCount(Demand demand) {
        // 1. 校验需求是否存在
        if (demand == null) {
            return null;
        }

        if (!StpUtil.isLogin()) {
            return demand;
        }
        if (CollUtil.isEmpty(demand.getViewUserIds())) {
            demand.setViewUserIds(new ArrayList<>());
        }
        String userId = StpUtil.getLoginIdAsString();
        List<String> viewUserIds = demand.getViewUserIds();
        viewUserIds.add(userId);
        viewUserIds = viewUserIds.stream().distinct().collect(Collectors.toList());

        // 2. 数据库层面直接+1（原子操作，避免先查后改的并发问题）
        demand.setViewUserIds(viewUserIds);
        updateById(demand);
        return demand;
    }

    /**
     * 访问数减1（确保不小于0）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response decrementViewCount(String demandId) {
        // 1. 校验需求是否存在
        Demand demand = demandMapper.selectById(demandId);
        if (demand == null) {
            return Response.buildFailure("100", "需求不存在");
        }

        // 2. 确保减1后不小于0（数据库层面判断）
        LambdaUpdateWrapper<Demand> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Demand::getId, demandId)
                .gt(Demand::getViewCount, 0)  // 仅当当前值>0时才更新
                .setSql("view_count = view_count - 1");

        int rows = demandMapper.update(null, updateWrapper);
        return rows > 0 ? Response.buildSuccess() : Response.buildFailure("100304", "更新失败");
    }

    /**
     * 更新需求表的点赞数/点踩数
     */
    @Override
    public void updateDemandInteractCount(String demandId, DemandInteractTypeEnum type, int num) {
        LambdaUpdateWrapper<Demand> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Demand::getId, demandId);

        if (DemandInteractTypeEnum.LIKE.equals(type)) {
            updateWrapper.setSql("like_count = like_count + " + num);
        } else if (DemandInteractTypeEnum.DISLIKE.equals(type)) {
            updateWrapper.setSql("dislike_count = dislike_count + " + num);
        }

        demandMapper.update(null, updateWrapper);

    }

    @Override
    public void updateDemandCollectionCount(String demandId, DemandCollectionTypeEnum type, int num) {
        LambdaUpdateWrapper<Demand> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Demand::getId, demandId);

        if (DemandCollectionTypeEnum.collection.equals(type)) {
            updateWrapper.setSql("collect_count = collect_count + " + num);
        } else if (DemandCollectionTypeEnum.cancelCollection.equals(type)) {
            updateWrapper.setSql("collect_count = collect_count + " + num);
        }

        demandMapper.update(null, updateWrapper);
    }

    @Override
    public DemandVO selectById(String id) {
        Demand entity = demandMapper.selectById(id);
        entity = incrementViewCount(entity);

        DemandVO vo =
                ConvertUtils.copyBean(entity, DemandVO.class);
        if (vo == null) {
            return vo;
        }

        takeUserVO(vo);


        DemandInteract demandInteract = demandInteractServiceImpl.selectByDemandIdUserId(id, StpUtil.getLoginIdAsString());
        vo.setIsLiked(false);
        vo.setIsDisliked(false);
        if (demandInteract != null) {
            if (demandInteract.getType() == DemandInteractTypeEnum.LIKE) {
                vo.setIsLiked(true);
            } else if (demandInteract.getType() == DemandInteractTypeEnum.DISLIKE) {
                vo.setIsDisliked(true);
            }
        }

        List<String> collectIdList = demandCollectionService.listDemandIdByUserId(StpUtil.getLoginIdAsString());
        vo.setCollect(CollUtil.isNotEmpty(collectIdList) && collectIdList.contains(vo.getId()));
        return vo;
    }

    @Override
    public IPage<DemandVO> pageVo(DemandQuery query) {
        IPage<Demand> page = new Page<Demand>(query.getCurrent(), query.getSize());
        page = page(page, new LambdaQueryWrapper<Demand>());
        Page<DemandVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        List<DemandVO> records = ConvertUtils.copyBeanList(page.getRecords(), DemandVO.class);
        voPage.setRecords(records);
        return voPage;
    }

    @Override
    public IPage<DemandVO> userPageVo(DemandUserQuery query) {
        IPage<Demand> page = new Page<Demand>(query.getCurrent(), query.getSize());
        page = page(page, new LambdaQueryWrapper<Demand>()
                .eq(Demand::getUserId, query.getUserId())
                .eq(Objects.nonNull(query.getType()), Demand::getType, query.getType())
                .orderByDesc(Demand::getCreateTime)
        );
        Page<DemandVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        List<DemandVO> records = ConvertUtils.copyBeanList(page.getRecords(), DemandVO.class);
        voPage.setRecords(records);
        takeUserVO(voPage.getRecords());
        return voPage;
    }

/*
    public void takeUserVO(DemandVO demandVO) {
        if (Objects.isNull(demandVO)) {
            return;
        }

        if (StringUtils.isBlank(demandVO.getUserId())) {
            return;
        }
        User user = userService.getById(demandVO.getUserId());  // 假设User的id字段也是String类型
        UserSimpleVO userSimpleVO = new UserSimpleVO();
        if (user != null) {
            userSimpleVO.setName(user.getName());  // 用户名/昵称
            userSimpleVO.setHeadImg(user.getHeadImg());  // 用户头像
        } else {
            // 未匹配到用户，设置默认值
            userSimpleVO.setName(SystemConstant.DEFAULT_NAME);
            userSimpleVO.setHeadImg(SystemConstant.DEFAULT_HEAD_IMG);
        }
        demandVO.setUserSimpleVO(userSimpleVO);  // 未匹配到用户时不显示手机号
    }
*/

    /**
     * 分页查询需求列表（支持筛选和排序）
     */
    @Override
    public IPage<DemandVO> wxHomePage(DemandQuery query) {
        IPage<Demand> page = new Page<Demand>(query.getCurrent(), query.getSize());

        LambdaQueryWrapper<Demand> wrapper = new LambdaQueryWrapper<>();

        // 1. 状态筛选：仅显示正常状态（status=1）
        wrapper.eq(Demand::getStatus, 1);

        // 2. 关键词搜索：模糊匹配标题或描述
        if (StringUtils.isNotBlank(query.getKeyWord())) {
            wrapper.like(Demand::getTitle, query.getKeyWord())
                    .or()
                    .like(Demand::getDescription, query.getKeyWord());
        }

        // 3. 分类筛选：若type非空且不为"全部"，则匹配分类
        if (StringUtils.isNotBlank(query.getTag())) {
            List<String> tagList = systemConfigService.getTagWithOneLevelChildren(query.getTag());
            wrapper.in(Demand::getTag, tagList);
        }        // 3. 行业筛选：若type非空且不为"全部"，则匹配分类
        if (CollUtil.isNotEmpty(query.getIndustryList())) {
            List<String> industryList = IndustryEnum.getSelfAndChildren(query.getIndustryList());
            wrapper.in(Demand::getIndustry, industryList);
        }

        // 4. 地区筛选：若cityCode非空，匹配地区编码
        if (StringUtil.isNotBlank(query.getCityCode())) {
            List<String> codeList = cityService.getSingleWithChildren(query.getCityCode());
            if (CollUtil.isNotEmpty(codeList)) {
                wrapper.in(Demand::getCityCode, codeList);
            } else {
                return new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
            }
        }


        // 5. 排序规则：根据sort参数动态处理
        String sort = query.getOrderField();
        // 处理默认推荐排序（为空或推荐）
        DemandSortEnum sortType = StringUtils.isBlank(sort) ?
                DemandSortEnum.RECOMMEND :
                DemandSortEnum.valueOfDbValue(sort);

        switch (sortType) {
            case RECOMMEND:
                // 推荐排序：优先VIP置顶（未过期），再按发布时间倒序
                if (StpUtil.isLogin()) {
                    List<String> tags = userFollowPostTypeService.getByUserId(StpUtil.getLoginIdAsString());
                    if (CollUtil.isNotEmpty(tags)) {
                        String tagsStr = tags.stream()
                                .collect(Collectors.joining("','", "'", "'"));
                        // 加入排序：推荐好友优先，再按活跃度降序（可根据需求调整次要排序）
                        wrapper.last("ORDER BY CASE WHEN tag IN (" + tagsStr + ") THEN 1 ELSE 0 END DESC, create_time DESC");
                    } else {
                        wrapper.orderByDesc(Demand::getCreateTime);
                    }

                    /*
                    List<UserResourceVO> userResourceVOList = userResourceService.selectByUserId(StpUtil.getLoginIdAsString());
                    if (CollUtil.isNotEmpty(userResourceVOList)) {
                        List<String> nameList = userResourceVOList.stream().map(UserResourceVO::getName).collect(Collectors.toList());
                        List<String> listResult = IKAnalyzerUtils.splitList(nameList);
                        if (CollUtil.isNotEmpty(listResult)) {
//                            wrapper.like(Demand::getDescription, query.getKeyWord());
                            // 4. 获取当前用户的推荐好友ID列表
                        }
                    }
                    */
                } else {
                    wrapper.orderByDesc(Demand::getCreateTime);
                }
                break;
            case NEWEST:
                // 最新排序：按发布时间倒序
                wrapper.orderByDesc(Demand::getCreateTime);
                break;
            case LIKE_MOST:
                // 点赞最多：按点赞数倒序
                wrapper.orderByDesc(Demand::getLikeCount);
                break;
            case COLLECT_MOST:
                // 收藏最多：按收藏数倒序
                wrapper.orderByDesc(Demand::getCollectCount);
                break;
        }
        // 执行分页查询
        page = page(page, wrapper);

        Page<DemandVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        List<DemandVO> records = ConvertUtils.copyBeanList(page.getRecords(), DemandVO.class);
        voPage.setRecords(records);


        // 2. 补充当前用户的点赞/点踩状态
        // 2.1 获取当前用户ID（假设从查询参数或上下文获取，需根据实际登录逻辑调整）

        // 2.2 若用户未登录，直接设置默认状态（未点赞/未点踩）
        if (!StpUtil.isLogin()) {
            records.forEach(vo -> {
                vo.setIsLiked(false);
                vo.setIsDisliked(false);
            });
            takeUserVO(records); // 原有用户信息处理
            return voPage;
        }

        String currentUserId = StpUtil.getLoginIdAsString(); // 或从SecurityContext获取：SecurityUtils.getCurrentUserId()

        List<String> demandIds = records.stream()
                .map(DemandVO::getId)
                .collect(Collectors.toList());

        List<Map<String, Object>> userActions = demandInteractServiceImpl.queryUserActions(currentUserId, demandIds);
        List<String> collectIdList = demandCollectionService.listDemandIdByUserId(currentUserId);
        Map<String, Map<String, Boolean>> actionMap = new HashMap<>();
        for (Map<String, Object> action : userActions) {
            String demandId = (String) action.get("demandId");
            Integer type = (Integer) action.get("type");

            actionMap.computeIfAbsent(demandId, k -> new HashMap<>())
                    .put("isLiked", type == 1); // 1=点赞
            actionMap.computeIfAbsent(demandId, k -> new HashMap<>())
                    .put("isDisliked", type == -1); // -1=点踩
        }

        // 2.6 为每个需求VO设置状态
        records.forEach(vo -> {
            Map<String, Boolean> actions = actionMap.getOrDefault(vo.getId(), new HashMap<>());
            vo.setIsLiked(actions.getOrDefault("isLiked", false));
            vo.setIsDisliked(actions.getOrDefault("isDisliked", false));
            vo.setCollect(CollUtil.isNotEmpty(collectIdList) && collectIdList.contains(vo.getId()));
        });

        takeUserVO(records); // 原有用户信息处理
        return voPage;
    }

    @Override
    public IPage<DemandVO> userCollectionPage(DemandUserQuery query) {
        List<String> idList = demandCollectionService.listDemandIdByUserId(query.getUserId());
        IPage<Demand> page = new Page<Demand>(query.getCurrent(), query.getSize());

        if (CollUtil.isEmpty(idList)) {
            return new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        }

        LambdaQueryWrapper<Demand> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Demand::getId, idList)
                .orderByDesc(Demand::getCreateTime);
        page = page(page, wrapper);

        Page<DemandVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        List<DemandVO> records = ConvertUtils.copyBeanList(page.getRecords(), DemandVO.class);
        voPage.setRecords(records);

        String currentUserId = StpUtil.getLoginIdAsString(); // 或从SecurityContext获取：SecurityUtils.getCurrentUserId()

        List<String> demandIds = records.stream()
                .map(DemandVO::getId)
                .collect(Collectors.toList());

        List<Map<String, Object>> userActions = demandInteractServiceImpl.queryUserActions(currentUserId, demandIds);
        List<String> collectIdList = demandCollectionService.listDemandIdByUserId(currentUserId);
        Map<String, Map<String, Boolean>> actionMap = new HashMap<>();
        for (Map<String, Object> action : userActions) {
            String demandId = (String) action.get("demandId");
            Integer type = (Integer) action.get("type");

            actionMap.computeIfAbsent(demandId, k -> new HashMap<>())
                    .put("isLiked", type == 1); // 1=点赞
            actionMap.computeIfAbsent(demandId, k -> new HashMap<>())
                    .put("isDisliked", type == -1); // -1=点踩
        }


        // 2.6 为每个需求VO设置状态
        records.forEach(vo -> {
            Map<String, Boolean> actions = actionMap.getOrDefault(vo.getId(), new HashMap<>());
            vo.setIsLiked(actions.getOrDefault("isLiked", false));
            vo.setIsDisliked(actions.getOrDefault("isDisliked", false));
            vo.setCollect(CollUtil.isNotEmpty(collectIdList) && collectIdList.contains(vo.getId()));
        });


        takeUserVO(voPage.getRecords());
        return voPage;
    }

    @Override
    public void takeUserVO(List<DemandVO> list) {
        if (CollUtil.isEmpty(list)) {
            return;
        }
        List<String> userIds = list.stream()
                .map(DemandVO::getUserId)
                .filter(StringUtils::isNotBlank)  // 过滤空字符串
                .collect(Collectors.toList());

        if (CollUtil.isEmpty(userIds)) {
            return;
        }
        List<User> userList = userService.listByIds(userIds);  // 假设User的id字段也是String类型
        Map<String, User> userMap = userList.stream()
                .collect(Collectors.toMap(
                        User::getId,  // 以用户ID作为key（String类型）
                        user -> user,
                        (existing, replacement) -> existing  // 若有重复ID，保留第一个
                ));

        Map<String, Boolean> vipMap = userVipTimeServiceImpl.getVipStatusByUserIds(userIds);

        list.forEach(demandVO -> {
            String userId = demandVO.getUserId();
            User matchedUser = StringUtils.isNotBlank(userId) ? userMap.get(userId) : null;
            UserSimpleVO userSimpleVO = new UserSimpleVO();
            if (matchedUser != null) {
                userSimpleVO.setName(matchedUser.getName());  // 用户名/昵称
                userSimpleVO.setHeadImg(matchedUser.getHeadImg());  // 用户头像
                userSimpleVO.setImUserSig(matchedUser.getImUserSig());
                if (CollUtil.isEmpty(matchedUser.getExtraPhones())) {
                    userSimpleVO.setContactMobile(matchedUser.getCellphone());
                } else {
                    userSimpleVO.setContactMobile(matchedUser.getExtraPhones().get(0));
                }
                if (CollUtil.isNotEmpty(vipMap)) {
                    if (Objects.nonNull(vipMap.get(userId))) {
                        if (vipMap.get(userId)) {
                            userSimpleVO.setVip(true);
                        }
                    }
                }

            } else {
                // 未匹配到用户，设置默认值
                userSimpleVO.setName(SystemConstant.DEFAULT_NAME);
                userSimpleVO.setHeadImg(SystemConstant.DEFAULT_HEAD_IMG);
            }
            demandVO.setUserSimpleVO(userSimpleVO);  // 未匹配到用户时不显示手机号
        });
    }

    @Override
    public Response refreshTop(String demandId) {
        // 校验需求是否存在
        Demand demand = getById(demandId);
        if (Objects.isNull(demand)) {
            return Response.buildFailure("100", "需求不存在");
        }
        // 更新置顶状态为置顶（假设1表示置顶）
        LambdaUpdateWrapper<Demand> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Demand::getId, demandId)
                .set(Demand::getCreateTime, LocalDateTime.now());
        boolean result = update(updateWrapper);
        return result ? Response.buildSuccess() : Response.buildFailure("100304", "刷新置顶失败");
    }

    @Override
    public Response takeOffShelves(String demandId) {
        // 校验需求是否存在
        Demand demand = getById(demandId);
        if (Objects.isNull(demand)) {
            return Response.buildFailure("100", "需求不存在");
        }
        Byte status = -1;
        if (Objects.equals(demand.getStatus(), (byte) -1)) {
            status = 1;
            if (Objects.equals(demand.getStatusByBack(), Boolean.TRUE)) {
                return Response.buildFailure("100", "管理员操作下架,无法操作");
            }
        }


        // 更新状态为下架（假设 -1表示下架）
        LambdaUpdateWrapper<Demand> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Demand::getId, demandId)
                .set(Demand::getStatus, status);
        boolean result = update(updateWrapper);
        return result ? Response.buildSuccess() : Response.buildFailure("100304", "操作失败");
    }

    @Override
    public boolean checkUserPermission(String demandId, String userId) {
        Demand demand = getById(demandId);
        return Objects.nonNull(demand) && demand.getUserId().equals(userId);
    }

    // ========================== 条件分页查询实现 ==========================
    @Override
    public Page<DemandVO> pageAdminDemand(AdminDemandQuery query) {
        // 1. 参数校验：避免空查询导致异常
        if (query == null) {
            return new Page<>(query.getCurrent(), query.getSize());
        }

        // 2. 构建分页对象：从query中获取当前页和每页条数
        Page<Demand> page = new Page<>(query.getCurrent(), query.getSize());
        // 构建筛选条件：复用工具方法，统一筛选逻辑
        LambdaQueryWrapper<Demand> wrapper = buildAdminDemandWrapper(query);

        // 3. 关联用户表分页查询：获取带发布人名称的分页数据
        page = page(page, wrapper);
        // 5. 封装分页VO结果：保留总条数、总页数等分页信息
        Page<DemandVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        List<DemandVO> records = ConvertUtils.copyBeanList(page.getRecords(), DemandVO.class);
        voPage.setRecords(records);

        takeUserVO(voPage.getRecords());
        return voPage;
    }

    // ========================== POI导出Excel实现 ==========================
    @Override
    public void exportAdminDemandExcel(AdminDemandQuery query, HttpServletResponse response) {
        // 参数校验：若query为null，初始化空查询（查全部数据）
        if (query == null) {
            query = new AdminDemandQuery();
        }

        try {
            // 1. 查询全量数据：设置超大size，避免分页截断数据
            query.setCurrent(1L);
            query.setSize(Long.MAX_VALUE);
            LambdaQueryWrapper<Demand> wrapper = buildAdminDemandWrapper(query);
            List<Demand> list = list(wrapper);

            List<DemandVO> dataList = ConvertUtils.copyBeanList(list, DemandVO.class);
            takeUserVO(dataList);
            // 无数据时抛出异常，提示前端
            if (CollUtil.isEmpty(dataList)) {
                throw new RuntimeException("无符合条件的帖子数据，无法导出");
            }

            // 2. 创建Excel工作簿：XSSF格式支持大量数据，避免OOM
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("已发布帖子列表");
            sheet.setDefaultColumnWidth(25); // 默认列宽：适配长文本（如内容详情）

            // 3. 构建表头：与页面展示字段一一对应，顺序一致
            String[] headers = {
                    "帖子标题", "分类", "帖子类型", "发布时间", "最近刷新时间",
                    "发布人", "浏览量", "收藏量", "踩Ta量", "紧急程度",
                    "资源有效期", "隐私保护类型", "状态", "内容详情", "附件内容"
            };
            // 表头样式：字体加粗，提升可读性
            CellStyle headerStyle = workbook.createCellStyle();
            Font headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerStyle.setFont(headerFont);
            // 写入表头：第0行为表头
            Row headerRow = sheet.createRow(0);
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
                cell.setCellStyle(headerStyle);
            }

            // 4. 填充数据行：逐行处理，避免空指针，适配Excel单元格格式
            for (int i = 0; i < dataList.size(); i++) {
                DemandVO demand = dataList.get(i);
                Row dataRow = sheet.createRow(i + 1); // 从第1行开始（第0行为表头）

                // 帖子标题：处理null，避免单元格空值
                dataRow.createCell(0).setCellValue(Objects.nonNull(demand.getTitle()) ? demand.getTitle() : "");
                // 分类：枚举中文描述（如“二级类别A-5”）
                String tagDesc = Objects.nonNull(demand.getTag()) ? demand.getTag() : "";
                dataRow.createCell(1).setCellValue(tagDesc);
                // 帖子类型：枚举中文描述（如“需要资源”）
                String typeDesc = Objects.nonNull(demand.getType()) ? demand.getType().getName() : "";
                dataRow.createCell(2).setCellValue(typeDesc);
                // 发布时间：格式化为“yyyy-MM-dd HH:mm”，适配页面展示习惯
                String createTime = Objects.nonNull(demand.getCreateTime())
                        ? demand.getCreateTime().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
                        : "";
                dataRow.createCell(3).setCellValue(createTime);
                // 最近刷新时间：复用发布时间（刷新时更新createTime字段）
                dataRow.createCell(4).setCellValue(demand.getRefreshTime());
                // 发布人名称：关联用户表的name字段
                dataRow.createCell(5).setCellValue(Objects.nonNull(demand.getUserSimpleVO()) ? demand.getUserSimpleVO().getName() : "");
                // 浏览量：默认0，避免null导致Excel显示异常
                int viewCount = Objects.nonNull(demand.getViewCount()) ? demand.getViewCount() : 0;
                dataRow.createCell(6).setCellValue(viewCount);
                // 收藏量：默认0
                int collectCount = Objects.nonNull(demand.getCollectCount()) ? demand.getCollectCount() : 0;
                dataRow.createCell(7).setCellValue(collectCount);
                // 踩Ta量：对应dislikeCount字段，默认0
                int dislikeCount = Objects.nonNull(demand.getDislikeCount()) ? demand.getDislikeCount() : 0;
                dataRow.createCell(8).setCellValue(dislikeCount);
                // 紧急程度：枚举中文描述（如“紧急”）
                String urgencyDesc = Objects.nonNull(demand.getResourceUrgency()) ? demand.getResourceUrgency().getName() : "";
                dataRow.createCell(9).setCellValue(urgencyDesc);
                // 资源有效期：区分“长期有效”和具体过期时间
                String expireDesc = Boolean.TRUE.equals(demand.getNeverExpire())
                        ? "资源长期有效"
                        : (Objects.nonNull(demand.getExpireTime())
                        ? demand.getExpireTime().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
                        : "未设置");
                dataRow.createCell(10).setCellValue(expireDesc);
                // 隐私保护类型：枚举中文描述（如“仅平台的虚拟号码联系自己”）
                String privacyDesc = Objects.nonNull(demand.getPhonePrivacy()) ? demand.getPhonePrivacy().getName() : "";
                dataRow.createCell(11).setCellValue(privacyDesc);
                // 状态：中文描述（如“上架”）
                dataRow.createCell(12).setCellValue(getStatusDesc(demand.getStatus()));
                // 内容详情：保留原始描述，支持长文本
                dataRow.createCell(13).setCellValue(Objects.nonNull(demand.getDescription()) ? demand.getDescription() : "");
                // 附件内容：List<String>拼接为“附件1，附件2”格式，适配Excel单元格
                String fileDesc = CollUtil.isNotEmpty(demand.getFileList())
                        ? String.join("，", demand.getFileList())
                        : "无附件";
                dataRow.createCell(14).setCellValue(fileDesc);
            }

            // 5. 设置响应头：配置下载信息，解决中文文件名乱码
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            // 文件名：格式“已发布帖子列表_时间.xlsx”，替换冒号避免系统兼容问题
            String fileName = "已发布帖子列表_" + LocalDateTime.now().toString().replace(":", "-") + ".xlsx";
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Pragma", "public"); // 兼容HTTP/1.0
            response.setHeader("Cache-Control", "max-age=30"); // 缓存30秒，提升体验
            ExcelTool.setExportFileName(response, "已发布帖子列表");

            // 6. 输出Excel流：try-with-resources自动关闭流，避免资源泄漏
            try (OutputStream outputStream = response.getOutputStream()) {
                workbook.write(outputStream);
                outputStream.flush(); // 强制刷新流，确保数据完整输出
            } finally {
                workbook.close(); // 手动关闭工作簿，释放POI资源
            }

        } catch (IOException e) {
            log.error("导出已发布帖子Excel：IO异常", e);
            throw new RuntimeException("导出Excel失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("导出已发布帖子Excel：未知异常", e);
            throw new RuntimeException("导出Excel异常：" + e.getMessage());
        }
    }

    @Override
    public List<Map<String, Object>> countByAreaCodes() {
        return demandMapper.countByAreaCodes();
    }

    // ========================== 工具方法（复用逻辑） ==========================

    /**
     * 构建后台管理-帖子列表的多条件筛选器
     * 分页查询和导出Excel共用此方法，确保筛选逻辑一致
     *
     * @param query 筛选条件实体
     * @return 构建后的LambdaQueryWrapper
     */
    private LambdaQueryWrapper<Demand> buildAdminDemandWrapper(AdminDemandQuery query) {
        LambdaQueryWrapper<Demand> wrapper = new LambdaQueryWrapper<>();

        // 1. 关键词筛选：模糊匹配标题或描述
        if (StringUtils.isNotBlank(query.getKeyWord())) {
            wrapper.like(Demand::getTitle, query.getKeyWord())
                    .or()
                    .like(Demand::getDescription, query.getKeyWord());
        }

        // 2. 枚举类型筛选：分类、帖子类型、紧急程度、隐私保护类型
        if (StringUtils.isNotBlank(query.getTag())) {
            List<String> tagList = systemConfigService.getTagWithOneLevelChildren(query.getTag());
            wrapper.in(Demand::getTag, tagList);
        }
        wrapper.eq(query.getDemandType() != null, Demand::getType, query.getDemandType())
                .eq(query.getResourceUrgency() != null, Demand::getResourceUrgency, query.getResourceUrgency())
                .eq(query.getPhonePrivacy() != null, Demand::getPhonePrivacy, query.getPhonePrivacy());

        // 3. 状态筛选：匹配指定状态（如1-上架）
        wrapper.eq(query.getStatus() != null, Demand::getStatus, query.getStatus());

        // 4. 发布人名称筛选：先查用户ID列表，再用Demand.userId IN (列表) 筛选
        if (StringUtils.isNotBlank(query.getPublisherName())) {
            // 4.1 调用UserService查询匹配的用户ID列表（模糊匹配名称）
            List<String> userIdList = userService.listUserIdsByName(query.getPublisherName());

            // 4.2 处理ID列表：为空时加无效条件（确保无数据返回），不为空时加IN条件
            if (CollUtil.isEmpty(userIdList)) {
                wrapper.eq(Demand::getUserId, ""); // 匹配不存在的ID，避免全表扫描
            } else {
                wrapper.in(Demand::getUserId, userIdList); // 用用户ID列表筛选需求
            }
        }

        // 5. 发布时间范围筛选：大于等于开始时间，小于等于结束时间
        if (query.getStartCreateTime() != null) {
            wrapper.ge(Demand::getCreateTime, query.getStartCreateTime());
        }
        if (query.getEndCreateTime() != null) {
            wrapper.le(Demand::getCreateTime, query.getEndCreateTime());
        }

        // 6. 刷新时间范围筛选：复用createTime字段（刷新时更新该字段）
        if (query.getStartRefreshTime() != null) {
            wrapper.ge(Demand::getRefreshTime, query.getStartRefreshTime());
        }
        if (query.getEndRefreshTime() != null) {
            wrapper.le(Demand::getRefreshTime, query.getEndRefreshTime());
        }

        // 7. 默认排序：按最近刷新时间（createTime）倒序，确保最新数据在前
        wrapper.orderByDesc(Demand::getRefreshTime);

        return wrapper;
    }


    /**
     * 为DemandVO补充用户简单信息（发布人昵称、头像）
     * 未匹配到用户时，使用系统默认值（如“未知用户”“默认头像”）
     *
     * @param demandVO 需要补充用户信息的DemandVO
     */
    @Override
    public void takeUserVO(DemandVO demandVO) {
        if (demandVO == null || StringUtils.isBlank(demandVO.getUserId())) {
            return;
        }
        // 查询用户信息：通过userId关联User表
        User user = userService.getById(demandVO.getUserId());
        UserSimpleVO userSimpleVO = new UserSimpleVO();
        if (user != null) {
            userSimpleVO.setName(user.getName()); // 发布人昵称
            userSimpleVO.setHeadImg(user.getHeadImg()); // 发布人头像
            userSimpleVO.setImUserSig(user.getImUserSig());

            if (CollUtil.isEmpty(user.getExtraPhones())) {
                userSimpleVO.setContactMobile(user.getCellphone());
            } else {
                userSimpleVO.setContactMobile(user.getExtraPhones().get(0));
            }

        } else {
            // 未匹配到用户：设置系统默认值
            userSimpleVO.setName(SystemConstant.DEFAULT_NAME);
            userSimpleVO.setHeadImg(SystemConstant.DEFAULT_HEAD_IMG);
        }
        demandVO.setUserSimpleVO(userSimpleVO);
    }

    /**
     * 将状态码转换为中文描述
     * 对应状态定义：0-隐藏，1-上架，2-删除，-1-下架
     *
     * @param status 状态码（Byte类型）
     * @return 状态中文描述
     */
    private String getStatusDesc(Byte status) {
        if (status == null) {
            return "未知";
        }
        return switch (status) {
            case 0 -> "隐藏";
            case 1 -> "上架";
            case 2 -> "删除";
            case -1 -> "下架";
            default -> "未知";
        };
    }

    // ========================== 帖子刷新（置顶）接口实现 ==========================
    @Override
    @Transactional(rollbackFor = Exception.class) // 事务控制：更新失败回滚
    public Response refreshDemand(String demandId) {
        // 1. 参数校验：demandId不能为空
        if (StringUtils.isBlank(demandId)) {
            return Response.buildFailure("100302", "帖子ID不能为空");
        }

        // 2. 校验帖子是否存在
        Demand demand = getById(demandId);
        if (Objects.isNull(demand)) {
            return Response.buildFailure("100", "帖子不存在或已删除");
        }

        // 4. 执行刷新：更新发布时间为当前时间（实现置顶效果，排序时靠前）
        LambdaUpdateWrapper<Demand> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Demand::getId, demandId)
                .set(Demand::getCreateTime, LocalDateTime.now()); // 刷新时间=当前时间

        boolean result = update(updateWrapper);
        if (result) {
            log.info("帖子刷新成功，demandId:{}", demandId);
            return Response.buildSuccess();
        } else {
            log.error("帖子刷新失败，demandId:{}", demandId);
            return Response.buildFailure("100304", "帖子刷新失败，请重试");
        }
    }

    // ========================== 帖子下架接口实现 ==========================
    @Override
    @Transactional(rollbackFor = Exception.class) // 事务控制：更新失败回滚
    public Response takeOffDemand(String demandId) {
        // 1. 参数校验：demandId不能为空
        if (StringUtils.isBlank(demandId)) {
            return Response.buildFailure("100302", "帖子ID不能为空");
        }

        // 2. 校验帖子是否存在且未下架
        Demand demand = getById(demandId);
        if (Objects.isNull(demand)) {
            return Response.buildFailure("100", "帖子不存在或已删除");
        }
        // 若已下架，直接返回成功（避免重复操作）
        if (demand.getStatus() == -1) {
            return Response.buildSuccess();
        }

        // 4. 执行下架：更新状态为-1（下架）
        LambdaUpdateWrapper<Demand> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Demand::getId, demandId)
                .set(Demand::getStatus, (byte) -1)
                .set(Demand::getStatusByBack, true)
        ; // 状态：-1=下架

        boolean result = update(updateWrapper);
        if (result) {
            log.info("帖子下架成功，demandId:{}", demandId);
            return Response.buildSuccess();
        } else {
            log.error("帖子下架失败，demandId:{}", demandId);
            return Response.buildFailure("100304", "帖子下架失败，请重试");
        }
    }

    // ========================== 复用原有工具方法 ==========================

    // ========================== 帖子上架接口实现 ==========================
    @Override
    @Transactional(rollbackFor = Exception.class) // 事务控制：更新失败回滚
    public Response takeOnDemand(String demandId) {
        // 1. 参数校验：demandId不能为空
        if (StringUtils.isBlank(demandId)) {
            return Response.buildFailure("100302", "帖子ID不能为空");
        }

        // 2. 校验帖子是否存在且未上架
        Demand demand = getById(demandId);
        if (Objects.isNull(demand)) {
            return Response.buildFailure("100", "帖子不存在或已删除");
        }
        // 若已上架，直接返回成功（避免重复操作）
        if (demand.getStatus() == 1) {
            return Response.buildSuccess();
        }

        // 4. 执行上架：更新状态为-1（上架）
        LambdaUpdateWrapper<Demand> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Demand::getId, demandId)
                .set(Demand::getStatus, (byte) 1)
                .set(Demand::getStatusByBack, false)
        ; // 状态：1=上架

        boolean result = update(updateWrapper);
        if (result) {
            return Response.buildSuccess();
        } else {
            return Response.buildFailure("100304", "帖子上架失败，请重试");
        }
    }

    @Override
    public List<Map<String, Object>> countByAreaAndType() {
        return demandMapper.countByAreaAndType();
    }

    @Override
    public List<DemandVO> selectByUserId(String userId) {
        List<Demand> list = list(new LambdaQueryWrapper<Demand>().eq(Demand::getUserId, userId).last("limit 20"));
        List<DemandVO> records = ConvertUtils.copyBeanList(list, DemandVO.class);

        String currentUserId = StpUtil.getLoginIdAsString(); // 或从SecurityContext获取：SecurityUtils.getCurrentUserId()

        List<String> demandIds = records.stream()
                .map(DemandVO::getId)
                .collect(Collectors.toList());

        List<Map<String, Object>> userActions = demandInteractServiceImpl.queryUserActions(currentUserId, demandIds);
        List<String> collectIdList = demandCollectionService.listDemandIdByUserId(currentUserId);
        Map<String, Map<String, Boolean>> actionMap = new HashMap<>();
        for (Map<String, Object> action : userActions) {
            String demandId = (String) action.get("demandId");
            Integer type = (Integer) action.get("type");

            actionMap.computeIfAbsent(demandId, k -> new HashMap<>())
                    .put("isLiked", type == 1); // 1=点赞
            actionMap.computeIfAbsent(demandId, k -> new HashMap<>())
                    .put("isDisliked", type == -1); // -1=点踩
        }


        // 2.6 为每个需求VO设置状态
        records.forEach(vo -> {
            Map<String, Boolean> actions = actionMap.getOrDefault(vo.getId(), new HashMap<>());
            vo.setIsLiked(actions.getOrDefault("isLiked", false));
            vo.setIsDisliked(actions.getOrDefault("isDisliked", false));
            vo.setCollect(CollUtil.isNotEmpty(collectIdList) && collectIdList.contains(vo.getId()));
        });

        return records;
    }

    @Override
    public Map<String, String> selectOwnerMapByTargetIds(List<String> targetIds) {
        if (CollUtil.isEmpty(targetIds)) {
            return new HashMap<>();
        }
        List<Map<String, String>> list = demandMapper.selectOwnerMapByTargetIds(targetIds);
        Map<String, String> result = new HashMap<>();
        list.forEach(map -> {
            String targetId = map.get("target_id");
            String ownerUserId = map.get("owner_user_id");
            if (targetId == null || ownerUserId == null) {
                return;
            }
            // 用 LinkedHashSet 去重并保留顺序，最后转 List
            result.put(targetId, ownerUserId);
        });
        return result;

    }

    // ========================== 复用原有工具方法 ==========================


}